
package com.smart.common.config;

import com.smart.common.utils.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 需求:能否编辑一个HttpClientAPI,简化程序远程调用的过程
 * 简化策略:
 * 用户使用:传递参数
 * 结果:远程访问的返回值
 * 参数说明:
 * arg0:url地址,arg1:Map<key,value> 封装参数,arg2:指定字符集编码
 */
@Component
public class HttpClientTemplate {
    @Autowired
    private CloseableHttpClient httpClient;
    @Autowired
    private RequestConfig requestConfig;

    public String doGet(String url, Map<String, String> params, String charset) {
        String result = null;
        try {
            HttpGet httpGet = new HttpGet(url);
            if (params != null) {
                // 处理参数，构建完整的 URL
                StringBuilder sb = new StringBuilder(url);
                if (url.indexOf('?') == -1) {
                    sb.append('?');
                } else {
                    sb.append('&');
                }
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    sb.append(entry.getKey()).append('=').append(entry.getValue()).append('&');
                }
                httpGet.setURI(URI.create(sb.deleteCharAt(sb.length() - 1).toString()));
            }

            httpGet.setConfig(requestConfig);

            HttpResponse httpResponse = httpClient.execute(httpGet);
            // 检查响应状态码
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = httpResponse.getEntity();
                // 确保 charset 不为 null
                if (charset == null) {
                    charset = "UTF-8"; // 使用默认字符集
                }
                // 处理响应体
                result = EntityUtils.toString(entity, charset);
            } else {
                throw new RuntimeException("HTTP request failed with status code: " + httpResponse.getStatusLine().getStatusCode());
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("HTTP request failed: " + e.getMessage(), e);
        }
        return result;
    }

    public String doGet(String url) {
        return doGet(url, null, null);
    }

    public String doGet(String url, Map<String, String> params) {
        return doGet(url, params, null);
    }

    public String doGet(String url, String charset) {
        return doGet(url, null, charset);
    }

    // 实现 httpClient POST 提交
    public String doPost(String url, Map<String, String> params, String charset) {
        String result = null;

        // 1. 定义请求类型
        HttpPost post = new HttpPost(url);
        post.setConfig(requestConfig); // 定义超时时间

        // 2. 判断字符集是否为 null
        if (StringUtils.isEmpty(charset)) {
            charset = "UTF-8";
        }

        // 3. 判断用户是否传递参数
        if (params != null) {
            // 3.2 准备 List 集合信息
            List<NameValuePair> parameters = new ArrayList<>();

            // 3.3 将数据封装到 List 集合中
            for (Map.Entry<String, String> entry : params.entrySet()) {
                parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }

            // 3.1 模拟表单提交
            try {
                org.apache.http.client.entity.UrlEncodedFormEntity formEntity = new org.apache.http.client.entity.UrlEncodedFormEntity(parameters, charset); // 采用 u8 编码

                // 3.4 将实体对象封装到请求对象中
                post.setEntity(formEntity);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        // 4. 发送请求
        try {
            CloseableHttpResponse response = httpClient.execute(post);

            // 4.1 判断返回值状态
            if (response.getStatusLine().getStatusCode() == 200) {
                // 4.2 表示请求成功
                result = EntityUtils.toString(response.getEntity(), charset);
            } else {
                System.out.println("获取状态码信息: " + response.getStatusLine().getStatusCode());
                throw new RuntimeException();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return result;
    }

    public String doPost(String url) {
        return doPost(url, null, null);
    }

    public String doPost(String url, Map<String, String> params) {
        return doPost(url, params, null);
    }

    public String doPost(String url, String charset) {
        return doPost(url, null, charset);
    }

    // 新增 doPostJson 方法
    public String doPostJson(String url, String json, String charset) {
        String result = null;

        // 1. 定义请求类型
        HttpPost post = new HttpPost(url);
        post.setConfig(requestConfig); // 定义超时时间

        // 2. 判断字符集是否为 null
        if (StringUtils.isEmpty(charset)) {
            charset = "UTF-8";
        }

        // 3. 设置请求头
        post.setHeader("Content-Type", "application/json; charset=" + charset);

        // 4. 设置请求体
        StringEntity entity = new StringEntity(json, charset);
        post.setEntity(entity);

        // 5. 发送请求
        try {
            CloseableHttpResponse response = httpClient.execute(post);

            // 6. 判断返回值状态
            if (response.getStatusLine().getStatusCode() == 200) {
                // 7. 表示请求成功
                result = EntityUtils.toString(response.getEntity(), charset);
            } else {
                System.out.println("获取状态码信息: " + response.getStatusLine().getStatusCode());
                throw new RuntimeException("HTTP request failed with status code: " + response.getStatusLine().getStatusCode());
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("HTTP request failed: " + e.getMessage(), e);
        }

        return result;
    }

    public String doPostJson(String url, String json) {
        return doPostJson(url, json, null);
    }
}